<?php declare(strict_types=1);

namespace App\Services\Withhold\TL;

use App\Models\Bi\BillLog;
use App\Models\Bi\RefundLog;
use App\Models\MechanismMerchant;
use App\Models\Store;
use App\Models\StoreAllPayWayList;
use App\Services\PrintSqlService;
use App\Services\Store\StoreMchService;
use App\Util\ExeclUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;

class BillLogService
{
    protected function chuckGet($transaction_date, MechanismMerchant $v): array
    {
        //获取表名
        $tableName = date("Ym", strtotime($transaction_date . " 23:59:59"));
        if (Schema::connection("bi")->hasTable("bill_logs_" . $tableName)) {
            $query = BillLog::query()->from("bill_logs_" . $tableName); //bi_bill_logs_202503
        } else {
            $query = BillLog::query(); //bi_bill_logs_202503
        }
        //判断生效时间
        $start_date = $transaction_date . " 00:00:00";
        $end_date = $transaction_date . " 23:59:59";
        $bind_date = date("Y-m-d H:i:s", $v->now_time);
        if ($start_date >= $bind_date) {
            $start_date = $bind_date;
        }
        $query->whereBetween("pay_time", [$start_date, $end_date]);
        $query->where("day", date("Y-m-d", strtotime($end_date)));
        //使用索引 pid,所以单独查询
        $query->where("store_pid", $v->merchant_id);
//        $query->where("out_trade_no", "20250408144520520413210");
//        $query->where("status", 2);
        //查询代扣模式的数据
        $query->where("receive_model", 2);
        $dataList = $query->select(["device_code", "store_id", "store_pid", "company",
            "pay_time", "status", "total_fee", "fee_amount", "refund_fee", "pay_type", "out_trade_no", "refund_no", "trade_no", "day",
            "created_at"
        ])->get()->toArray();
        return $dataList;
    }


    public function tlRun(array $where, string $inst_no_day)
    {
        $institution = MechanismMerchant::query()
            ->where([
                'mechanism_id' => $where["institution_number"],
//                "merchant_id" => "20211118155217503420"
            ])
            ->select(['merchant_id', 'now_time'])->get(); // 商户id
        if (empty($institution)) {
            throw new \Exception("机构号下不存在店铺");
        }
        foreach ($institution as $v) {
            $dataList = $this->billLogOneDay($where, $v);
            //制作文件
            $this->makeTxt($dataList, $inst_no_day, config("withhold.tl.file_path"));
        }
    }

    public function billLogOneDay(array $where, MechanismMerchant $v): array
    {

        //全部的总店数据,由于开始时间不一样。需要分开查询并且汇总
        //两组数据查询，并且合并
        $dataList = $this->chuckGet($where["transaction_date"], $v);
        //退款数据是有限的 直接in查询
        $refundNos = [];
        $orderRefundNos = [];
        foreach ($dataList as $v) {
            if ($v["status"] == 2) {
                $refundNos[] = $v["refund_no"];
                $orderRefundNos[] = $v["out_trade_no"];
            }
        }
        $refundNos = array_unique($refundNos);
        $orderRefundNos = array_unique($orderRefundNos);
        $refund = [];
        $orderRefund = [];
        if (!empty($refundNos)) {
            $refund = RefundLog::query()->whereIn("refund_no", $refundNos)->get()->toArray();
            $refund = array_combine(array_column($refund, "refund_no"), $refund);
            //获取支付订单
        }
        if (!empty($orderRefundNos)) {
            $orderRefund = BillLog::query()->whereIn("out_trade_no", $orderRefundNos)->where("status", 1)->get()->toArray();
            $orderRefund = array_combine(array_column($orderRefund, "out_trade_no"), $orderRefund);
        }
        //返回list中
        foreach ($dataList as $k => $v) {
            if ($v["status"] == 2) {
                $v["refundObject"] = $refund[$v["refund_no"]];
                $v["payRefundObject"] = $orderRefund[$v["out_trade_no"]];
                $dataList[$k] = $v;
            }
        }
        return $dataList;
    }

    public function makeTxt(array $data, string $inst_no_day, string $path): void
    {
        //创建文件
        $filePath = storage_path($path . '/' . $inst_no_day . ".txt");
//        $sum = storage_path($path . '/' . $inst_no_day . "_sum.txt");
//        if (!file_exists($sum)) {
//            file_put_contents($sum, json_encode([
//                "total_fee" => 0,
//                "refund_fee" => 0,
//                "fee_amount" => 0
//            ]));
//        }
        foreach ($data as $v) {
            Log::channel("withhold")->info("makeTxt", ["out_trade_no" => $v["out_trade_no"]]);
//            这个我看了，传过来的退款订单交易金额是原交易金额，不是填的退款金额，所以存在差异，手续费是对得上
//            商户号，终端号，交易时间，退款完成时间，交易金额（分），手续费金额（分），退款金额（分），结算金额（分），交易类型，支付方式，交易状态，交易单号，退款原单号，终端流水号，渠道订单号，交易日期，用户标识，银行卡类型，附加数据，
            $str = "";
            $str .= $v["store_pid"] . ","; //商户号
            $str .= $v["store_id"] . ",";  //终端号
            //处理隔日退
            if ($v["status"] == 1) {
                $pay_time = $v["pay_time"];
//                if (date("Ymd", strtotime($pay_time)) != date("Ymd", strtotime($v["created_at"]))) {
//                    $pay_time = $v["created_at"];
//                }
                $str .= $pay_time . ",";  //交易时间
                $str .= ","; //查询退款时间
                $str .= ($v["total_fee"] * 100) . ","; //交易金额
            } else {
                $str .= ($v["refundObject"]["created_at"]) . ",";  //交易时间
                $str .= ($v["refundObject"]["created_at"]) . ","; //查询退款时间
                $str .= ($v["refund_fee"] * 100) . ","; //交易金额
            }
//            $tmp["fee_amount"] = bcadd((string)$tmp["fee_amount"], (string)$v["fee_amount"], 2);;
            $str .= $v["fee_amount"] * 100 . ","; //手续费金额 支付成功为正值 退款为负值 （手续费必须有值，实际扣款金额以该值为准！）
            $str .= ($v["refund_fee"] * 100) . ",";//退款金额
            if ($v["status"] == 1) {
                $str .= bcmul(bcsub(bcsub((string)$v["total_fee"], (string)$v["refund_fee"], 2), (string)$v["fee_amount"], 2), "100") . ",";//结算金额（分）
            } else {
                //退款金额+退款手续费=结算金额(取负数)
                $str .= "-" . bcmul(bcadd((string)$v["refund_fee"], (string)$v["fee_amount"], 2), "100") . ",";//结算金额（分）
            }
            //交易类型 1 微信 2支付宝 3银行卡 4 现金 5无卡支付 6qq钱包 7百度钱包8京东钱包 10翼支付 11云闪付 17招行支付
            if ($v["pay_type"] == 1) {
                $str .= "1,";
            } else if ($v["pay_type"] == 2) {
                $str .= "2,";
            } else if ($v["pay_type"] == 3) {
                $str .= "10,";
            } else if ($v["pay_type"] == 4) {
                $str .= "11,";
            } else if ($v["pay_type"] == 5) {
                $str .= "3,";
            }
//            支付方式
            //被扫支付1，扫码支付2，公众号支付3，wap支付4 app支付5，小程序支付6，刷脸支付7
            $str .= "1,"; //支付成功1，已撤销4, 退款成功5
//            交易状态
            if ($v["status"] == 1) {
                $str .= "1,"; //支付成功1，已撤销4, 退款成功5
            } else {
                $str .= "5,"; //支付成功1，已撤销4, 退款成功5
            }
//            商户号，终端号，交易时间，退款完成时间，交易金额（分），手续费金额（分），退款金额（分），结算金额（分），交易类型，支付方式，交易状态，交易单号，退款原单号，终端流水号，渠道订单号，交易日期，用户标识，银行卡类型，附加数据，
            //交易单号
            if ($v["status"] == 1) {
                $str .= $v["out_trade_no"] . ","; //交易单号
                $str .= $v["refund_no"] . ","; //退款原单号
            } else {
                $rand = (($v["refund_no"] ?? "") . date("YmdHis", time()) . rand(100000000, 999999999));
                $rand = strrev($rand);
                $rand = substr($rand, 0, 30);
                $str .= $rand . ","; //交易单号
                $str .= $v["out_trade_no"] . ","; //退款原单号
            }
            $str .= $v["out_trade_no"] . ","; //终端流水号
            $str .= ($v["trade_no"] ?? $v["out_trade_no"]) . ","; //渠道订单号
            $str .= ($v["day"]) . ","; //交易日期
            $str .= ","; // 用户标识
            $str .= "0,"; //银行卡类型
            $str .= ","; //附加数据
//            if ($v["status"] == 1) {
//                $str .= "支付-" . $v["out_trade_no"] . ","; //附加数据 支付成功1，已撤销4, 退款成功5
//            } else {
//                $str .= "退款-" . $v["out_trade_no"] . ",";  //附加数据 支付成功1，已撤销4, 退款成功5
//            }

            file_put_contents($filePath, $str . "\r\n", FILE_APPEND);
            //总金额计算
//            $total_tmp = $refund_tmp = 0;
//            if ($v["status"] == 1) {
//                $total_tmp += $v["total_fee"]; //支付成功1，已撤销4, 退款成功5
//            } else {
//                $refund_tmp -= $v["refund_fee"]; //支付成功1，已撤销4, 退款成功5
//            }
//            $tmp = json_decode(file_get_contents($sum), true);
//            $tmp["total_fee"] = bcadd((string)$tmp["total_fee"], (string)$total_tmp, 2);
//            $tmp["refund_fee"] += $refund_tmp;
//            $tmp["fee_amount"] = bcadd((string)$tmp["fee_amount"], (string)$v["fee_amount"], 2);;
//            file_put_contents($sum, json_encode($tmp));
        }
    }


    public function makeExecl(array $data, string $date, $store_number): string
    {
        //在这里导出
        $title = [
            "商户编号", "终端号", "交易时间", "交易金额（元）", "交易手续费（元）", "支付方式", "流水类型", "交易订单号", "退款订单号", "清算日期", "通道类型",
        ];
        $company = StoreAllPayWayList::query()->get()->toArray();
        $companyArray = array_combine(array_column($company, "company"), $company);
        $value = [];
        foreach ($data as $k => $v) {
            $pay_type = "";
            switch ($v["pay_type"]) {
                case 1:
                    $pay_type = "微信支付";
                    break;
                case 2:
                    $pay_type = "支付宝";
                    break;
                case 3:
                    $pay_type = "翼支付";
                    break;
                case 4:
                    $pay_type = "云闪付";
                    break;
                case 5:
                    $pay_type = "刷卡支付";
                    break;
            }
            $total_amount = $v["total_fee"];
            $fee_amount = $v["fee_amount"];
            $status_desc = "支付流水";
            if ($v["status"] == 2) {
                $status_desc = "退款流水";
                $total_amount = "-" . $v["refund_fee"];
                $fee_amount = "-" . $v["fee_amount"];
            }
            $value[] = [
                $v["store_pid"],
                $v["device_code"],
                $v["pay_time"],
                $total_amount,
                $fee_amount,
                $pay_type,
                $status_desc,
                $v["out_trade_no"],
                $v["refund_no"],
                $date,
                $companyArray[$v["company"]]["company_desc"] ?? "",
            ];
        }
        //写入excel
        $util = new ExeclUtil();
        $fileName = "代扣账单流水_" . $date . "_" . $store_number . ".csv";//xlsx
        $filePath = public_path("/uploads/withhold/TL/" . date("Y/md", time()) . "/");
        if (!is_dir($filePath)) {
            mkdir($filePath, 0777, true);
        }
        $util->exportToExcel($filePath . $fileName, [], $title, $value);
        $url = $util->uploadOss($filePath . $fileName, $fileName);
        //删除文件
        if (file_exists($filePath . $fileName)) {
            unlink($filePath . $fileName);
        }
        //删除fileName
        return $url;

    }

}